/**
 * 在现代计算机体系结构中，最小的可寻址内存单元是字节。
 * 由于所有对象都需要具有唯一的内存地址，这意味着对象的大小必须至少为一字节。
 * 对于大多数变量类型来说，这很好。然而，对于布尔值来说，这有点浪费（双关语）。
 * 布尔类型只有两种状态：true (1) 或 false (0)。这组状态只需要一位来存储。
 * 但是，如果变量必须至少为一个字节，并且一个字节为 8 位，则意味着布尔值使用 1 位，而其余 7 位未使用。
 * 
 * 最佳实践
 *   位操作是少数应明确使用无符号整数（或 std::bitset）的情况之一。
 * 
 * 位编号和位位置
 *   给定一个位序列，我们通常从右到左对位进行编号，从 0（而不是 1）开始。每个数字表示一个位位置。
 *   76543210  Bit position
 *   00000101  Bit sequence
 * 
 * 通过 std::bitset 操作位
 * std::bitset 提供了 4 个对于进行位操作很有用的关键成员函数：
 *   test() 允许我们查询一个位是 0 还是 1。
 *   set() 允许我们打开一个位（如果该位已经打开，这将不会执行任何操作）。
 *   reset() 允许我们关闭某个位（如果该位已经关闭，则不会执行任何操作）。
 *   Flip() 允许我们将一个位值从 0 翻转到 1，反之亦然。
 *   
 *   一些其它常用的成员函数
 *   size() 返回位集中的位数。
 *   count() 返回位集中设置为 的位数true。这可用于确定是否所有位都为 0 或者任何位为 1。
 *   all() 返回一个布尔值，指示是否所有位都设置为true。
 *   any() 返回一个布尔值，指示是否有任何位设置为true。
 *   none() 返回一个布尔值，指示是否没有位设置为true。
 * 
 */

#include <bitset>
#include <iostream>

int main()
{
    std::bitset<8> me{ 0b0000'0101 }; // we need 8 bits, start with bit pattern 0000 0101
    me.set(3);   // set bit position 3 to 1 (now we have 0000 1101)
    me.flip(4);  // flip bit 4 (now we have 0001 1101)
    me.reset(4); // set bit 4 back to 0 (now we have 0000 1101)

    std::cout << "All the bits: " << me << '\n';
    std::cout << "Bit 3 has value: " << me.test(3) << '\n';
    std::cout << "Bit 4 has value: " << me.test(4) << '\n';


    // 给位命名可以帮助我们的代码更具可读性
    [[maybe_unused]] constexpr int  isHungry   { 0 };
    [[maybe_unused]] constexpr int  isSad      { 1 };
    [[maybe_unused]] constexpr int  isMad      { 2 };
    [[maybe_unused]] constexpr int  isHappy    { 3 };
    [[maybe_unused]] constexpr int  isLaughing { 4 };
    [[maybe_unused]] constexpr int  isAsleep   { 5 };
    [[maybe_unused]] constexpr int  isDead     { 6 };
    [[maybe_unused]] constexpr int  isCrying   { 7 };

    std::bitset<8> me1{ 0b0000'0101 }; // we need 8 bits, start with bit pattern 0000 0101
    me1.set(isHappy);      // set bit position 3 to 1 (now we have 0000 1101)
    me1.flip(isLaughing);  // flip bit 4 (now we have 0001 1101)
    me1.reset(isLaughing); // set bit 4 back to 0 (now we have 0000 1101)

    std::cout << "All the bits: " << me1 << '\n';
    std::cout << "I am happy: " << me1.test(isHappy) << '\n';
    std::cout << "I am laughing: " << me1.test(isLaughing) << '\n';


    std::bitset<8> bits{ 0b0000'1101 };
    std::cout << bits.size() << " bits are in the bitset\n";
    std::cout << bits.count() << " bits are set to true\n";

    std::cout << std::boolalpha;
    std::cout << "All bits are true: " << bits.all() << '\n';
    std::cout << "Some bits are true: " << bits.any() << '\n';
    std::cout << "No bits are true: " << bits.none() << '\n';

    return 0;
}